﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.Runtime.Session;
using Hicap.AuthorizationServer.Core;
using Hicap.AuthorizationServer.Core.Caches.Sys;
using Hicap.AuthorizationServer.Core.Caches.Sys.Interface;
using Hicap.AuthorizationServer.Core.Domains.Authorization;
using Hicap.AuthorizationServer.Core.Models.Sys;
using Hicap.AuthorizationServer.Sys.AppService.Interface;
using Hicap.AuthorizationServer.Sys.DTO.AuthObjects;
using Microsoft.EntityFrameworkCore;

namespace Hicap.AuthorizationServer.Sys.AppService
{
    /// <summary>
    /// AuthObject应用层服务的接口实现方法
    /// </summary>
    public class AuthObjectAppService
       : AuthorizationServerAppServiceBase<AuthObject,
           AuthObjectAppService,
           AuthObjectEditDto,
           AuthObjectListDto,
           AuthObjectCacheItem>,
            IAuthObjectAppService
    {
        ////BCC/ BEGIN CUSTOM CODE SECTION
        ////ECC/ END CUSTOM CODE SECTION
        private readonly IRepository<AuthObject> _authObjectRepository;

        private readonly IAbpSession _session;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        /// <summary>
        /// 构造函数
        /// </summary>
        public AuthObjectAppService(
            IPermissionCheckerManager permissionCheckerManager,
            IUnitOfWorkManager unitOfWorkManager,
            IRepository<AuthObject> repository,
            IRepository<AuthObjectRoleRelated> authObjectRoleRelatedRepository,
            IAuthObjectCache cache, IAuthObjectCache authObjectCache, IAbpSession session)
            : base(
                repository,
                unitOfWorkManager,
                cache)
        {
            _unitOfWorkManager = unitOfWorkManager;
            _authObjectRepository = repository;
            _session = session;
            ForeignKeys.Add(x => x.ParentObject);
            CreateActions.Add(SetParentAsync);
            UpdateActions.Add(SetParentIdAsync);
        }

        public List<AuthObjectTreeDto> GetAuthObjectTree()
        {
            var alllist = GetQuery().Include(x => x.ParentObject).ToList();
            var rootlist = alllist.Where(x => x.ParentObject == null);
            var resultList = new List<AuthObjectTreeDto>();

            foreach (var item in rootlist)
            {
                var result = new AuthObjectTreeDto
                {
                    CurrentNode = item.MapTo<AuthObjectListDto>(),
                    Childs = GetAuthObjectSubTree(item, alllist)
                };
                resultList.Add(result);
            }

            List<AuthObjectTreeDto> GetAuthObjectSubTree(AuthObject node, List<AuthObject> leafs)
            {
                var subtree = leafs.Where(x => x.ParentObject != null && x.ParentObject.Id == node.Id);
                var subResult = new List<AuthObjectTreeDto>();
                foreach (var authObject in subtree)
                {
                    subResult.Add(new AuthObjectTreeDto()
                    {
                        CurrentNode = authObject.MapTo<AuthObjectListDto>(),
                        Childs = GetAuthObjectSubTree(authObject, leafs)
                    });
                }
                return subResult;
            }

            return resultList;
        }

        private void SetParentIdAsync(AuthObjectEditDto input, AuthObject dbEntity)
        {

                if (input.ParentObjectId.HasValue) dbEntity.ParentObject.Id = input.ParentObjectId.Value;

        }

        private  void SetParentAsync(AuthObjectEditDto input, AuthObject entity)
        {
            if (input.ParentObjectId.HasValue)
            {
                entity.ParentObject =  _authObjectRepository.Get(input.ParentObjectId.Value);
            }
        }
    }
}